#include "cloneitemtool.h"
#include "view/scene.h"
#include "item/item.h"
#include "command/clonecommand.h"

#include <QGraphicsSceneMouseEvent>
#include <QGraphicsColorizeEffect>

namespace SymbolEditor
{

    CloneItemTool::CloneItemTool(QObject *parent):
        AbstractTool (parent),
        m_state(WaitForActivation)
    {
        setLabel("<b>C</b>lone items");
        setShortcut(QKeySequence("e,c"));
        setIcon(QIcon::fromTheme("edit-copy"));
        updateAction();
    }

    QGraphicsItem *CloneItemTool::cloneItem(QGraphicsItem *item)
    {
        auto clone = static_cast<GraphicsItem*>(item)->clone();
        clone->setSelected(false);
        addGraphicalEffect(clone);
        return clone;
    }

    // TODO: Make this configuratble
    void CloneItemTool::addGraphicalEffect(QGraphicsItem *item)
    {
        QGraphicsColorizeEffect *effect = new QGraphicsColorizeEffect();
        effect->setColor(Qt::darkGray);
        effect->setStrength(.5);
        item->setGraphicsEffect(effect);
    }

    void CloneItemTool::addClones()
    {
        for (QGraphicsItem *item : scene()->selectedItems())
        {
            m_itemIdList << item->data(0).value<quint64>();
            auto clone = cloneItem(item);
            m_clones.append(clone);
            scene()->addItem(clone);
        }
    }

    void CloneItemTool::moveClones(const QPointF &pos)
    {
        auto delta = pos - m_destination;
        for (auto item: m_clones)
        {
            item->moveBy(delta.x(), delta.y());
        }
        m_destination = pos;
    }

    void CloneItemTool::removeClones()
    {
        qDeleteAll(m_clones);
        m_clones.clear();
        m_itemIdList.clear();
    }

    void CloneItemTool::activate(Scene *scene)
    {
        if (m_state != WaitForActivation)
        {
            desactivate();
        }
        // FIXME: auto-desactivate if no selected items
        setScene(scene);
        m_state = WaitForOrigin;
    }

    void CloneItemTool::desactivate()
    {
        switch (m_state)
        {
            case WaitForActivation:
            case WaitForOrigin:
                break;
            case WaitForDestination:
                removeClones();
                break;
        }
        setScene(nullptr);
    }

    void CloneItemTool::pushCommand()
    {
        auto translation = m_destination - m_origin;
        auto command = new CloneCommand;
        command->itemIdList = m_itemIdList;
        command->translation = translation;
        appendCommand(command);
    }

    bool CloneItemTool::mouseClickEvent(QGraphicsSceneMouseEvent *event)
    {
        switch (m_state)
        {
            case WaitForActivation:
                break;
            case WaitForOrigin:
            {
                m_origin = m_destination = event->scenePos();
                addClones();
                m_state = WaitForDestination;
                break;
            }
            case WaitForDestination:
            {
                // FIXME: Don't push command if translation is null
                moveClones(event->scenePos());
                pushCommand();
                removeClones();
                // FIXME: auto-desactivate
                m_state = WaitForOrigin;
                break;
            }
        }
        return true;
    }

    bool CloneItemTool::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
    {
        switch (m_state)
        {
            case WaitForActivation:
                break;
            case WaitForOrigin:
                break;
            case WaitForDestination:
            {
                moveClones(event->scenePos());
                break;
            }
        }
        return true;
    }
}
